﻿#region (C) Header Region @ 2012
//====================================================
// 文件: MPPersistence.cs
// 描述: 
// 路径: Antu.WebControls\Persistence\MPPersistence.cs
// ******************版本1 ******************
// 人员: 蔡金保    时间 : 2012/11/15 11:26:44
// 注释:
//====================================================
#endregion

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Web;
using System.Data;
using Antu.Core.DataAccess;
using System.Collections;

namespace Antu.WebControls
{
    /// <summary>
    /// 持久化控件 直接按规则定义控件名自动保存批量更新字段
    /// 注：该控件查找指定控件内所有控件，不管有多少层父控件，都可以查找的到，只要所有控件在指定的控件BindControl内即可，效率会差一点但非常通用
    /// 注：该控件任何数据库通用
    /// tag:cjb
    /// </summary>
    /// <example>
    ///    protected void Page_Load(object sender, EventArgs e)
    ///      {
    ///      Persistence1.Status = Antu.WebControls.Persistence.ConStatus.View;
    ///       if (!IsPostBack)
    ///       {
    ///            Persistence1.Table = "at_rizhi";
    ///            Persistence1.Key = "id";
    ///            Persistence1.KeyValue = Request["id"];
    ///            Persistence1.ConnStr = "User ID=neto2;Password=iam2.11;Data Source=fcjwwdb";
    ///        }
    ///        Persistence1.BindControl = this.Page.Form;
    ///       }
    ///protected void Button1_Click(object sender, EventArgs e)
    /// {
    ///     Persistence1.Update();
    /// }
    /// </example>
    [ToolboxData("<{0}:MPPersistence  runat=server></{0}:MPPersistence>")]
    public class MPPersistence : PlaceHolder
    {
        private string[] readControlAcrnyms = { "txt", "ddl", "ckb", "rdb", "lbl", "hfd", "cal" };
        public enum ConStatus
        {
            View,
            Edit,
        }

        /// <summary>
        /// 需要操作表的数据库连接（要再在IsPostBack内指定）
        /// </summary>
        public string ConnStr
        {
            get
            {
                return ViewState["ConnStr"] as string;
            }
            set
            {
                ViewState["ConnStr"] = value;
            }
        }
        /// <summary>
        /// 需要操作表的表名（要再在IsPostBack内指定）
        /// </summary>
        public string Table
        {
            get
            {
                return ViewState["Table"] as string;
            }
            set
            {
                ViewState["Table"] = value;
            }
        }
        /// <summary>
        /// 需要操作表的关键字（要再在IsPostBack内指定）
        /// </summary>
        public string Key
        {
            get
            {
                return ViewState["Key"] as string;
            }
            set
            {
                ViewState["Key"] = value;
            }
        }
        /// <summary>
        /// 需要操作表的关键字的值（要再在IsPostBack内指定）
        /// </summary>
        public string KeyValue
        {
            get
            {
                return ViewState["KeyValue"] as string;
            }
            set
            {
                ViewState["KeyValue"] = value;
            }
        }
        private Hashtable mapTable = null;
        private Control _BindControl = null;
        /// <summary>
        /// 需要绑定查找控件的母控件，可以指定最近一级的控件，可以缩短查找时间（不能在IsPostBack内指定），在该控件内将查找前缀为 "txt", "ddl", "ckb", "rdb", "lbl", "hfd", "cal"的控件
        /// </summary>
        public Control BindControl
        {
            get
            {
                return _BindControl;
            }
            set
            {
                _BindControl = value;
            }
        }
        public ConStatus constatu = ConStatus.Edit;
        /// <summary>
        /// 控制页面元素的可编辑状态
        /// </summary>
        public ConStatus Status
        {
            get
            {
                return constatu;
            }
            set
            {
                constatu = value;
            }
        }

        private DataTable GetTableDetail(string table, string key, string id)
        {
            string sql = "select * from " + table + " where " + key + "='" + id + "'";
            IDataAccess ida = DataFactory.GetInstance(false, DatabaseType.Oracle, ConnStr);
            DataTable dt;
            ida.RunSql(sql, out dt);
            return dt;
        }
        private bool InsertTable(string table, string key, string id, Hashtable data)
        {
            string strSql = "insert into " + table;
            strSql += "(";
            string keyClause = string.Empty;
            string valueClause = string.Empty;
            bool bHaveKey = false;

            foreach (string datakey in data.Keys)
            {
                if (data[datakey] == null || data[datakey].ToString() == string.Empty)
                {
                    continue;
                }
                keyClause += datakey;
                keyClause += ",";
                if (data[datakey].ToString().StartsWith("to_date("))
                {
                    valueClause += data[datakey];
                    valueClause += ",";

                }
                else
                {
                    valueClause += ("'" + data[datakey] + "'");
                    valueClause += ",";
                }

                if (datakey.ToLower().CompareTo(key.ToLower()) == 0)
                {
                    bHaveKey = true;
                }
            }
            //如果这个id不为空，则添加id值(不一定为主键)
            if (id != null && id != string.Empty)
            {
                if (!bHaveKey)
                {
                    keyClause += key;
                    valueClause += ("'" + id + "'");
                }
                else
                {
                    keyClause = keyClause.Remove(keyClause.Length - 1);
                    valueClause = valueClause.Remove(valueClause.Length - 1);
                }
            }
            else
            {
                keyClause = keyClause.Remove(keyClause.Length - 1);
                valueClause = valueClause.Remove(valueClause.Length - 1);
            }
            strSql += keyClause;
            strSql += ") VALUES (";
            strSql += valueClause;
            strSql += ")";

            //strSql += string.Format(" returning {0} into :newId", key);
            //retun into 只有orcla才有，不通用，这里不用
            IDataAccess ida = DataFactory.GetInstance(false, DatabaseType.Oracle, ConnStr);

            int retval = ida.RunSql(strSql);
            return retval > 0 ? true : false;

        }
        private bool UpdateTable(string table, string key, string id, Hashtable data)
        {
            string sql = "update " + table + " set ";
            foreach (string datakey in data.Keys)
            {
                if (data[datakey] != null)
                {
                    if (data[datakey].ToString().StartsWith("to_date("))
                    {
                        sql += (datakey + " = " + data[datakey] + ",");
                    }
                    else
                    {
                        sql += (datakey + " = '" + data[datakey] + "',");
                    }
                }
            }
            sql = sql.Remove(sql.Length - 1);
            sql += (" where " + key + "='" + id + "'");
            IDataAccess ida = DataFactory.GetInstance(false, DatabaseType.Oracle, ConnStr);
            int retval = ida.RunSql(sql);
            return retval > 0 ? true : false;

        }

        private void GetAllControl(Control control)
        {
            if (control.Controls.Count == 0)
                return;
            if (control.Controls.Count > 0)
            {
                foreach (Control childcontrol in control.Controls)
                {
                    foreach (string acronym in readControlAcrnyms)
                    {
                        if (childcontrol.ID != null && childcontrol.ID.StartsWith(acronym))
                        {
                            string fieldName = childcontrol.ID.Substring(acronym.Length);
                            mapTable[fieldName] = childcontrol.ID;
                        }
                    }
                    GetAllControl(childcontrol);
                }
            }
        }
        private void MapControl()
        {
            if (mapTable != null)
            {
                return;
            }
            mapTable = new Hashtable(32);
            GetAllControl(BindControl);
        }
        private string GetControlValue(Control control)
        {
            string strReturn = string.Empty;
            if (control is TextBox)
            {
                TextBox txt = (TextBox)control;
                strReturn = txt.Text;
            }
            else if (control is Label)
            { }
            else if (control is DropDownList)
            {
                DropDownList ddl = (DropDownList)control;
                strReturn = ddl.SelectedValue;
            }
            else if (control is CheckBox)
            {
                CheckBox ckb = (CheckBox)control;
                if (ckb.Checked)
                {
                    strReturn = "1";
                }
                else
                {
                    strReturn = "0";
                }
            }
            else if (control is HiddenField)
            {
                HiddenField hfd = (HiddenField)control;
                if (hfd.Value != string.Empty)
                {
                    strReturn = hfd.Value;
                }
            }
            else if (control is MPCalendar)
            {
                MPCalendar calendar = (MPCalendar)control;
                if (calendar.Text != string.Empty)
                {
                    strReturn = "to_date('" + calendar.Text + "','yyyy-mm-dd hh24:mi:ss')";
                }
            }
            return strReturn;
        }
        private Hashtable PopulateHashTable()
        {
            Hashtable datas = new Hashtable(32);
            foreach (string key in mapTable.Keys)
            {
                Control findControl = null;
                Control control = FindControl(findControl, BindControl, mapTable[key].ToString());
                if (control != null)
                {
                    if (control.GetType() != typeof(Label)) //去除lable，lable控件不参与数据库交互
                    {
                        datas[key] = GetControlValue(control);
                    }
                }
            }
            return datas;
        }

        private void FillControl(Control control, string value)
        {
            if (control is TextBox)
            {
                TextBox txt = (TextBox)control;
                txt.Text = value;
            }
            if (control is Label)
            {
                Label lbl = (Label)control;
                lbl.Text = value;
            }
            else if (control is DropDownList)
            {
                DropDownList ddl = (DropDownList)control;
                ddl.SelectedValue = value;
            }
            else if (control is HiddenField)
            {
                HiddenField hfdCtl = (HiddenField)control;
                hfdCtl.Value = value;
            }
            else if (control is CheckBox)
            {
                CheckBox ckb = (CheckBox)control;
                if (value == "1")
                    ckb.Checked = true;
                else
                    ckb.Checked = false;
            }
            else if (control is MPCalendar)
            {
                MPCalendar cal = (MPCalendar)control;
                string setvalue = value;
                if (!string.IsNullOrEmpty(value))
                {
                    setvalue = Convert.ToDateTime(setvalue).ToShortDateString();
                }
                cal.Text = setvalue.ToString();
            }

        }
        private void DoLockControl(Control control)
        {
            ControlCollection cc = BindControl.Controls;
            if (control is TextBox)
            {
                TextBox txt = (TextBox)control;
                txt.ReadOnly = true;
            }
            else if (control is DropDownList)
            {
                DropDownList ddl = (DropDownList)control;
                ddl.Enabled = false;
            }
            else if (control is CheckBox)
            {
                CheckBox ckb = (CheckBox)control;
                ckb.Attributes.Remove("onclick");
                if (control is RadioButton)
                {
                    ckb.InputAttributes.Add("onmousemove", @"javascript:var rdbList=document.getElementsByName(this.name);
                        if(rdbList!=null)
                        {
                            for(i=0;i<rdbList.length;i++)
                            {
                                if(rdbList[i].checked)
                                {
                                    this.title=rdbList[i].id;
                                    break;
                                }
                            }
                        }");
                    ckb.Attributes.Add("onclick", @"javascript:this.checked=false;if(this.title!='')
                        {var rdb=document.getElementById(this.title);if(rdb!=null){rdb.checked=true;}}");
                }
                else
                {
                    ckb.Attributes.Add("onclick", "javascript:this.checked=!this.checked;");
                }
            }
        }

        public void Update()
        {
            if (constatu == ConStatus.View)
            { HttpContext.Current.Response.Write("<script>alert('页面处于锁定状态，不可保存！');</script>"); }
            else
            {
                if (string.IsNullOrEmpty(KeyValue) || GetTableDetail(Table, Key, KeyValue).Rows.Count == 0)
                {
                    MapControl();
                    KeyValue = Guid.NewGuid().ToString().Replace("-", "").ToUpper();
                    if (!InsertTable(Table, Key, KeyValue, PopulateHashTable()))
                    {
                        throw new Exception("插入失败");
                    }
                }
                else
                {
                    MapControl();
                    if (!UpdateTable(Table, Key, KeyValue, PopulateHashTable()))
                    {
                        throw new Exception("更新失败");
                    }
                }
            }
        }
        private Control FindControl(Control findControl, Control control, string controlId)
        {
            if (findControl == null)
            {
                if (control.Controls.Count > 0)
                {
                    findControl = control.FindControl(controlId);
                    if (findControl == null)
                    {
                        for (int temp = 0; temp < control.Controls.Count; temp++)
                        {
                            if (control.Controls[temp].Controls.Count > 0)
                            {
                                if (findControl == null)
                                {
                                    findControl = FindControl(findControl, control.Controls[temp], controlId);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            return findControl;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (!((Page)HttpContext.Current.Handler).IsPostBack)
            {
                if (Table == null || Key == null)
                {
                    return;
                }
                DataTable dt = GetTableDetail(Table, Key, KeyValue);

                if (dt.Rows.Count == 0)
                {
                    return;
                }
                if (dt.Rows.Count > 0)
                {
                    MapControl();
                    DataRow row = dt.Rows[0];
                    if (Status == ConStatus.View)
                    {
                        foreach (string key in mapTable.Keys)
                        {
                            try
                            {
                                if (row[key] != null)
                                {
                                    Control findControl = null;
                                    Control control = FindControl(findControl, BindControl, mapTable[key].ToString());
                                    if (control == null)
                                        throw new Exception("未找到控件！");
                                    FillControl(control, row[key].ToString());
                                    DoLockControl(control);
                                }
                            }
                            catch { }
                        }
                    }
                    else if (Status == ConStatus.Edit)
                    {
                        foreach (string key in mapTable.Keys)
                        {
                            try
                            {
                                if (row[key] != null)
                                {
                                    Control findControl = null;
                                    Control control = FindControl(findControl, BindControl, mapTable[key].ToString());
                                    if (control == null)
                                        throw new Exception("未找到控件！");
                                    FillControl(control, row[key].ToString());
                                }
                            }
                            catch { }
                        }
                    }
                }
            }
        }
    }
}
